package io.github.frailty9.crserver.config

import cn.dev33.satoken.`fun`.strategy.SaCreateTokenFunction
import cn.dev33.satoken.json.SaJsonTemplate
import cn.dev33.satoken.solon.integration.SaTokenInterceptor
import cn.dev33.satoken.strategy.SaStrategy
import io.github.frailty9.crserver.utils.IdGeneratorImpl
import mu.KotlinLogging
import org.noear.snack.ONode
import org.noear.solon.annotation.Bean
import org.noear.solon.annotation.Configuration
import org.noear.solon.annotation.Init
import org.noear.solon.annotation.Inject

@Configuration
class SaTokenConfigure {
    val log = KotlinLogging.logger {  }

    @Inject
    private lateinit var idGenerator: IdGeneratorImpl

    @Init
    fun rewriteSaStrategy() {
        SaStrategy.instance.createToken =
            SaCreateTokenFunction { loginId, loginType -> idGenerator.nextId().toString() }
    }

    /**
     * 注册拦截器
     */
    @Bean(index = -100)
    fun saTokenInterceptor(): SaTokenInterceptor {
        val saTokenInterceptor = SaTokenInterceptor()
        // 启用注解鉴权
        saTokenInterceptor.isAnnotation = true
        // 无鉴权放行登录接口
        saTokenInterceptor.addExclude("/api/account/login")
        return saTokenInterceptor
    }

    /**
     * 自定义用于 redis 存储的 JSON 处理器
     *
     * 使用`Solon`内置的`Snack3`处理, 避免额外引入json库
     *
     * 注意: Snack4已发布, 未来Solon可能将使用Snack4, API发生变更与此方法不兼容
     *
     * [详情见Snack代码仓库](https://gitee.com/noear/snack-jsonpath)
     */
    @Bean
    fun saJsonTemplate(): SaJsonTemplate {
        return object : SaJsonTemplate {
            override fun objectToJson(obj: Any?): String? {
//                return SnackDecl().toJson(obj)
                return ONode.stringify(obj)
            }

            override fun <T : Any?> jsonToObject(jsonStr: String?, clazz: Class<T?>?): T? {
                return ONode.deserialize(jsonStr, clazz)
            }
        }
    }
}